home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / maestro / source / timeline / appcanva.c next >
Encoding:
C/C++ Source or Header  |  1993-06-15  |  13.4 KB  |  332 lines

  1. /*
  2.  * Copyright (c) 1990, 1991 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and 
  5.  * its documentation for any purpose is hereby granted without fee, provided
  6.  * that (i) the above copyright notices and this permission notice appear in
  7.  * all copies of the software and related documentation, and (ii) the name
  8.  * Stanford may not be used in any advertising or publicity relating to
  9.  * the software without the specific, prior written permission of
  10.  * Stanford.
  11.  * 
  12.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  13.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  14.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  15.  *
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  17.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
  18.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT
  19.  * ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY,
  20.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21.  * SOFTWARE.
  22.  */
  23.  
  24. /* $Header: /Source/Media/collab/TimeLine/RCS/appCanvas.c,v 1.1 92/05/29 14:39:32 drapeau Exp $ */
  25. /* $Log:    appCanvas.c,v $
  26.  * Revision 1.1  92/05/29  14:39:32  drapeau
  27.  * Modified CheckDoubleClick() function to correct a few small errors.
  28.  * The function now checks that some time has passed between the last
  29.  * click and this one.  It also uses more general (and safe) ways of
  30.  * getting the timestamp of the current event, using XView functions.
  31.  * These changes are the same as those in the Browse module's
  32.  * CheckDoubleClick() function, which was originally taken from this
  33.  * file and modified.
  34.  * 
  35.  * Revision 1.0  91/09/30  16:48:53  chua
  36.  * Update to version 1.0
  37.  * 
  38.  * Revision 0.48  91/09/25  13:45:55  chua
  39.  * Changed the instrument field, instInfo, to editInfo.
  40.  * 
  41.  * Revision 0.47  91/09/23  17:01:06  chua
  42.  * In the event handler, set the selectedInstrument variable to the instrument
  43.  * being clicked.
  44.  * 
  45.  * Revision 0.46  91/09/19  17:28:36  chua
  46.  * Make sure that variables are initialized properly.  Change formatting slightly,
  47.  * so that (if, for, while) statements with only one statement in them will not have
  48.  * braces.
  49.  * 
  50.  * Revision 0.45  91/09/16  14:37:09  chua
  51.  * In RearrangeInst, reset the PANEL_CLIENT_DATA in accordance with the order that the
  52.  * instrument is on the instrument list.
  53.  * 
  54.  * Revision 0.44  91/08/22  12:11:28  chua
  55.  * When checking for double click, make sure that the application is open before doing a
  56.  * show application.
  57.  * 
  58.  * Revision 0.43  91/08/21  16:50:34  chua
  59.  * Include a new function, CheckDoubleClick, which is called from both 
  60.  * DrawCanvasEventHandler and AppCanvasEventHandler to determine if a double
  61.  * click event has occurred.
  62.  * 
  63.  * Modified AppCanvasEventHandler to take care of double click events. 
  64.  * A double click on an icon will bring the application to the front.
  65.  * 
  66.  * Revision 0.42  91/08/16  16:55:14  chua
  67.  * Moved the RearrangeInst function to the top of the file.
  68.  * 
  69.  * Revision 0.41  91/08/09  15:10:54  chua
  70.  * *** empty log message ***
  71.  * 
  72.  * Revision 0.40  91/08/09  15:09:46  chua
  73.  * This file contains the event and repaint handlers for the App canvas. (the canvas which
  74.  * contains the application icons).
  75.  *  */
  76.  
  77. static char appCanvasrcsid[] = "$Header: /Source/Media/collab/TimeLine/RCS/appCanvas.c,v 1.1 92/05/29 14:39:32 drapeau Exp $";
  78.  
  79. #include "main.h"
  80.  
  81. static int appY;                            /* Previous y position of the mouse in the app canvas when dragging. */
  82. static int wasLeftDown;                            /* Keep track of whether the left mouse was click and/or dragged */
  83.  
  84. /*
  85.  * This function will rearrange the positions of the applications in the instrument list (if necessary).
  86.  * It first checks if there is a need to rearrange the applications. 
  87.  * If so, by making use of the parameters currentApp and yPos, pointers to the selected instrument node and the node where the mouse is on can be located.
  88.  * The nodes are then moved around according to where the mouse was dragged.
  89.  * Finally, the relative positions of each instrument node is updated to be consistent with their new position on the list.
  90.  */
  91. void RearrangeInst(tlFrame, currentApp, yPos)
  92.      TimeLineFramePtr tlFrame;
  93.      int currentApp;
  94.      int yPos;
  95. {
  96.   Instrument    *moveInst, *prevInst;
  97.   Instrument     *currentInst;
  98.   int         top;
  99.   int count;
  100.   
  101.   currentInst = (Instrument *) FindInstrument(currentApp, tlFrame);
  102.   if (currentInst == NULL) 
  103.     return;
  104.   top = 1;
  105.   if (yPos > currentInst->cableStart)
  106.   {
  107.     if (currentApp + 1 == tlFrame->chosenApp)                /* Moving to the same place. */
  108.       return;
  109.     top = 0;
  110.   }
  111.   else if (currentApp == tlFrame->chosenApp + 1)            /* Mouse on top half on icon and selected icon is the one above.  No change in list */
  112.     return;
  113.   if (top == 1) 
  114.   {
  115.     currentApp --;
  116.     if (currentApp >= 0) 
  117.       currentInst = (Instrument *) FindInstrument(currentApp, tlFrame);
  118.   }
  119.   prevInst = (Instrument *) FindInstrument(tlFrame->chosenApp - 1, tlFrame);
  120.   moveInst = (Instrument *) FindInstrument(tlFrame->chosenApp, tlFrame);
  121.   if (moveInst == NULL)
  122.     return;
  123.   if (prevInst == NULL)                            /* Remove the selected app from the list */
  124.     tlFrame->instHead = tlFrame->instHead->next;
  125.   else 
  126.     prevInst->next = moveInst->next;
  127.   if (currentApp < 0)                            /* Place the selected app in the new place */
  128.   {
  129.     moveInst->next = tlFrame->instHead;
  130.     tlFrame->instHead = moveInst;
  131.   }
  132.   else 
  133.   {
  134.     moveInst->next = currentInst->next;
  135.     currentInst->next = moveInst;
  136.   }
  137.   currentInst = tlFrame->instHead;
  138.   count = 0;
  139.   while (currentInst != NULL)                        /* Reassign the relative positions of each instrument by going down the list */
  140.   {
  141.     currentInst->relativePosition = count;
  142.     xv_set(currentInst->editInfo->NoteInfoList,                /* Attach the instrument's relative position as the PANEL_CLIENT_DATA. */
  143.        PANEL_CLIENT_DATA, currentInst->relativePosition,        /* Lets the program know which instrument the panel belongs to. */
  144.        NULL);
  145.     currentInst->cableStart = (IconHeight + IconGap) * count + FirstCableYPosition;
  146.     if (currentInst == moveInst) 
  147.       tlFrame->chosenApp = count;
  148.     count ++;
  149.     currentInst = currentInst->next;
  150.   }
  151.   AppCanvasRepaintHandler(tlFrame->TimeLine_window->AppCanvas, tlFrame->paintWinApp, /* Repaint the canvases to show the new positions */
  152.               tlFrame->dpyApp, tlFrame->xidApp, NULL);
  153.   ShowNewCanvas(tlFrame, xv_get(tlFrame->DrawScrollbarHor, SCROLLBAR_VIEW_START));
  154. }
  155.  
  156. /*
  157.  * Event callback function for `AppCanvas'.
  158.  * This function will first check if the timeline is in stop mode and if the event triggering the calling of this function is
  159.  * a button event.  If not, it will return.
  160.  * The function will then check which application has been chosen.
  161.  * If the user has clicked at the bottom of the App canvas, where there is no application icon (the space in line with the timeline, the function
  162.  * will not perform anything.
  163.  * If the user has selected an icon, a check is made to see if the same icon has already been selected.
  164.  * If so, it remains selected.
  165.  * If not, the previously selected icon is redrawn so that it appears deselected (raised), and the newly selected icon is redrawn so that it
  166.  * appears selected (sunken).
  167.  * If the user drags the icon, the procedure RearrangeInst is called, which will rearrange the applications in the order that the user desired.
  168.  */
  169. Notify_value AppCanvasEventHandler(win, event, arg, type)
  170.      Xv_window    win;
  171.      Event        *event;
  172.      Notify_arg    arg;
  173.      Notify_event_type type;
  174. {
  175.   int        tempChosenApp;                        /* The new chosen application */
  176.   char         buf[100];
  177.   Instrument     *currentInst;                        /* Pointer to the chosen instrument node */
  178.   TimeLineFramePtr tlFrame;
  179.   TimeLine_window_objects    *ip = (TimeLine_window_objects *) xv_get(win, XV_KEY_DATA, INSTANCE);
  180.  
  181.   tlFrame = TimeLineWindow[xv_get(ip->controls, PANEL_CLIENT_DATA)];
  182.   if (event_is_down(event) && tlFrame->status == StopMode 
  183.       && event_id(event) == MS_LEFT && tlFrame->numberOfApps > 0) 
  184.   {
  185.     tempChosenApp = event_y(event) / (IconHeight + IconGap);        /* Get the relative position of the mouse click, with respect to the height and
  186.                                        spacing of the icons */
  187.     if ((tempChosenApp + 1) <= tlFrame->numberOfApps) 
  188.     {                                    /* An application is now chosen */
  189.       currentInst = (Instrument *) FindInstrument(tempChosenApp, tlFrame);
  190.       if (currentInst == NULL) 
  191.     return notify_next_event_func(win, (Notify_event) event, arg, type);
  192.       tlFrame->selectedInstrument = currentInst;
  193.       if (CheckDoubleClick(event, tlFrame) == OK &&            /* Check for double click */
  194.       strcmp(currentInst->port->hostName, "App not open") != 0) 
  195.     ShowApplicationHandler(tlFrame->TimeLine_window->appButton, MENU_NOTIFY);
  196.       else 
  197.       {
  198.     wasLeftDown = 1;
  199.     appY = event_y(event) - IconHeight/2;
  200.     if (tlFrame->chosenApp != tempChosenApp) 
  201.     {
  202.       if (tlFrame->chosenApp >= 0) 
  203.         InstrumentDrawIcon(FindInstrument(tlFrame->chosenApp, tlFrame),
  204.                    Raised, tlFrame);            /* Redraw the previously chosen app so that it is raised */
  205.       InstrumentDrawIcon(currentInst, Sunken,
  206.                  tlFrame);                    /* Draw the newly chosen app so that it is sunken */
  207.       sprintf (buf, "(%s)", currentInst->port->appName);
  208.       xv_set (tlFrame->InsertBlankTimePopup->CurrentlyActiveTrackMsg,
  209.           PANEL_LABEL_STRING, buf,
  210.           NULL);
  211.       tlFrame->chosenApp = tempChosenApp;
  212.     }
  213.       }
  214.     }
  215.   }
  216.   else if (event_is_up(event))                        /* Mouse up */
  217.   {
  218.     if (wasLeftDown > 1)                        /* Perform the following only if there had been dragging */
  219.     {
  220.       XDrawRectangle(tlFrame->dpyApp, tlFrame->xidApp, tlFrame->gcLine, 
  221.              IconXOffset, appY,
  222.              IconHeight, IconHeight);
  223.       wasLeftDown = 0;
  224.       tempChosenApp = event_y(event) / (IconHeight + IconGap);       
  225.       if (tempChosenApp < 0) 
  226.     tempChosenApp = 0;
  227.       else if (tempChosenApp >= tlFrame->numberOfApps) 
  228.     tempChosenApp = tlFrame->numberOfApps - 1;
  229.       if (tempChosenApp != tlFrame->chosenApp) 
  230.     RearrangeInst(tlFrame, tempChosenApp, event_y(event));
  231.     }
  232.   }
  233.   else if (event_id(event) == LOC_DRAG && wasLeftDown)            /* Dragging */
  234.   {
  235.     if (wasLeftDown > 1) 
  236.       XDrawRectangle(tlFrame->dpyApp, tlFrame->xidApp, tlFrame->gcLine, 
  237.              IconXOffset, appY,
  238.              IconHeight, IconHeight);
  239.     wasLeftDown ++;
  240.     appY = event_y(event);
  241.     if (appY < 0)                            /* Set the lower and upper limits where the 'icon box' can move */
  242.       appY = 0;
  243.     else if (appY > tlFrame->numberOfApps * (IconHeight + IconGap)) 
  244.       appY = tlFrame->numberOfApps * (IconHeight + IconGap);
  245.     appY -= IconHeight/2;
  246.     XDrawRectangle(tlFrame->dpyApp, tlFrame->xidApp, tlFrame->gcLine, 
  247.            IconXOffset, appY,
  248.            IconHeight, IconHeight);
  249.   }
  250.   return notify_next_event_func(win, (Notify_event) event, arg, type);
  251. }
  252.  
  253. /*
  254.  * Repaint callback function for `AppCanvas'.
  255.  * This function will set the height and width for the canvases, where appropriate.
  256.  * It will then clear the AppCanvas and redraws all the instrument icons.
  257.  */
  258. void AppCanvasRepaintHandler(canvas, paint_window, display, xid, rects)
  259.      Canvas        canvas;
  260.      Xv_window    paint_window;
  261.      Display         *display;
  262.      Window          xid;
  263.      Rectlist    *rects;
  264. {
  265.   Instrument *instrument;
  266.   int type, instCount;
  267.   TimeLineFramePtr tlFrame;
  268.   TimeLine_window_objects    *ip = (TimeLine_window_objects *) xv_get(canvas, XV_KEY_DATA, INSTANCE);
  269.  
  270.   tlFrame = TimeLineWindow[xv_get(ip->controls, PANEL_CLIENT_DATA)];
  271.   SetCanvasHeight(tlFrame);
  272.   xv_set(tlFrame->TimeLine_window->AppCanvas,
  273.      XV_WIDTH, 112,
  274.      NULL);
  275.   XClearWindow(tlFrame->dpyApp, tlFrame->xidApp);            /* clear the whole display */
  276.   instCount = 0;
  277.   for (instrument = tlFrame->instHead; instrument != NULL; instrument = instrument->next) /* draw the instrument icons */
  278.   {
  279.     type = Raised;
  280.     if (tlFrame->chosenApp == instCount)                /* Check to see if the icon should be drawn raised or sunken */
  281.       type = Sunken;
  282.     InstrumentDrawIcon (instrument, type, tlFrame);
  283.     instCount++;
  284.   }
  285. }
  286.  
  287. /*
  288.  * This function checks if a double click event has occurred.  Both the time and mouse distance are taken into account.
  289.  */
  290. int CheckDoubleClick(event, tlFrame)
  291.      Event    *event;
  292.      TimeLineFramePtr tlFrame;
  293. {
  294.   static Event        lastEvent;
  295.   static int         initial = 1;
  296.   static int        timeThreshold;
  297.   short            returnValue = Error;
  298.   char             *clickTimeout;
  299.   int            deltaTime;
  300.   int            deltaX, deltaY;
  301.   struct timeval    thisTime, lastTime;
  302.   
  303.   if (initial == 1) 
  304.   {
  305.     timeThreshold = TimeThreshold;
  306.     clickTimeout = XGetDefault((Display *) xv_get(tlFrame->TimeLine_window->window, XV_DISPLAY), 
  307.                "OpenWindows", "MultiClickTimeout");        /* Get the timeout value from the Xdefaults database */
  308.     if (clickTimeout != NULL) 
  309.       timeThreshold = atoi(clickTimeout) * 100;
  310.     initial = 0;
  311.   }
  312.   if (event_is_up(event))                        /* only deal with mouse down events */
  313.     return returnValue;
  314.   if (event_action(event) == ACTION_SELECT && event_action(&lastEvent) == ACTION_SELECT ) 
  315.   {
  316.     thisTime = event_time(event);
  317.     lastTime = event_time(&lastEvent);
  318.     deltaTime  = (thisTime.tv_sec - lastTime.tv_sec) * 1000
  319.       + (thisTime.tv_usec - lastTime.tv_usec) / 1000;
  320.     if ((deltaTime > 0) && (deltaTime <= timeThreshold))        /* Is the time within bounds? */
  321.     {
  322.       deltaX    = abs(event_x(&lastEvent) - event_x(event));        /* Check if the distance is within DistanceThreshold */
  323.       deltaY    = abs(event_y(&lastEvent) - event_y(event));    
  324.       if (deltaX <= DistanceThreshold && deltaY <= DistanceThreshold)
  325.     returnValue = OK;
  326.     }
  327.   }
  328.   lastEvent = *event;
  329.   return returnValue;
  330. }                                    /* end function CheckDoubleClick */
  331.  
  332.